iT邦幫忙

2023 iThome 鐵人賽

DAY 7
0
Software Development

開心撰寫 PHPUnit系列 第 7

Day 07. 讓自己的程式進化 - 重構

  • 分享至 

  • xImage
  •  

什麼是重構

重構就是『在不改變外部行為的狀況下,改變程式結構或擴充程式功能』,所以我們在調整程式結構的時候就會希望滿足以下條件

  • 確認修改後的程式執行結果不變
  • 任何修改能夠快速得到修改後的執行結果

只要習慣 PHPStorm 或者是 VSCode + PHPUnit Test Explorer 的開發方式,就立刻滿足以上兩個條件了,所以希望大家要花點時間去練習上述的開發方式

範例(假設我們是 PHP 新手)

接到一個 a + b = c 的需求,在得知這樣的需求後我們可以馬上寫出以下的程式碼

<?php
// tests/CalculatorTest.php

namespace Recca0120\Ithome30\Tests;

use PHPUnit\Framework\TestCase;
use Recca0120\Ithome30\Calculator;

class CalculatorTest extends TestCase
{
    public function test_sum_5_3_equals_8()
    {
        $calculator = new Calculator();

        self::assertEquals(8, $calculator->sum(5, 3));
    }
}
<?php
// src/Calculator.php

namespace Recca0120\Ithome30;

class Calculator
{
    public function sum($a, $b)
    {
        return $a + $b;
    }
}

接下來又得到一個需求為 a + b + c = d 我們可以馬上寫出以下的程式碼

<?php
// tests/CalculatorTest.php

namespace Recca0120\Ithome30\Tests;

use PHPUnit\Framework\TestCase;
use Recca0120\Ithome30\Calculator;

class CalculatorTest extends TestCase
{
    public function test_sum_5_3_equals_8()
    {
        $calculator = new Calculator();

        self::assertEquals(8, $calculator->sum(5, 3));
    }
    
    public function test_sum_5_3_9_equals_8()
    {
        $calculator = new Calculator();

        self::assertEquals(17, $calculator->sum(5, 3, 9));
    }
}
<?php
// src/Calculator.php

namespace Recca0120\Ithome30;

class Calculator
{
    public function sum($a, $b, $c = 0)
    {
        return $a + $b + $c;
    }
}

接下來又得到一個需求為 a + b + c + d = e,這時我們就會覺得好煩啊,所以我們就可以把程式碼改為

<?php
// tests/CalculatorTest.php

namespace Recca0120\Ithome30\Tests;

use PHPUnit\Framework\TestCase;
use Recca0120\Ithome30\Calculator;

class CalculatorTest extends TestCase
{
    public function test_sum_5_3_equals_8()
    {
        $calculator = new Calculator();

        self::assertEquals(8, $calculator->sum(5, 3));
    }

    public function test_sum_5_3_9_equals_8()
    {
        $calculator = new Calculator();

        self::assertEquals(17, $calculator->sum(5, 3, 9));
    }

    public function test_sum_5_3_9_4_equals_8()
    {
        $calculator = new Calculator();

        self::assertEquals(21, $calculator->sum(5, 3, 9, 4));
    }
}

<?php
// src/Calculator.php

namespace Recca0120\Ithome30;

class Calculator
{
    public function sum()
    {
        $numbers = func_get_args();
        $result = 0;

        foreach ($numbers as $number) {
            $result += $number;
        }

        return $result;
    }
}

這樣就滿足了所有需求並且有所的測試都通過了,過了幾天後突然看到了Variable-length argument lists這一篇,發現這個比較好閱讀,所以我們就馬上可以把 Calculator 調整為(測試不變)

<?php
// src/Calculator.php

namespace Recca0120\Ithome30;

class Calculator
{
    public function sum(...$numbers)
    {
        $result = 0;

        foreach ($numbers as $number) {
            $result += $number;
        }

        return $result;
    }
}

又突然在某天看到了array_reduce,我們又可以把程式碼改為(修改完請立即執行一次PHPUnit)

<?php
// src/Calculator.php

namespace Recca0120\Ithome30;


class Calculator
{
    public function sum(...$numbers)
    {
        return array_reduce($numbers, function ($carry, $number) {
            return $carry + $number;
        }, 0);
    }
}

又突然在某天看到了Arrow Functions,我們又可以把程式碼改為(修改完請立即執行一次PHPUnit)

<?php
// src/Calculator.php

namespace Recca0120\Ithome30;


class Calculator
{
    public function sum(...$numbers)
    {
        return array_reduce($numbers, fn ($carry, $number) => $carry + $number, 0);
    }
}

又突然在某天看到了array_sum,我們又可以把程式碼改為(修改完請立即執行一次PHPUnit)

<?php
// src/Calculator.php

namespace Recca0120\Ithome30;


class Calculator
{
    public function sum(...$numbers)
    {
        return array_sum($numbers);
    }
}

雖然這是一個非常簡單的例子,但從上面的歷程來看,我們可以從只會 for 迴圈的程式新手,經過重構的過程讓我們變成程式大師並且程式碼變的容易閱讀


上一篇
Day 06. 讓 PHPStorm 來幫助自己寫測試 - 實戰篇
下一篇
Day 08. 用測試來寫爬蟲 - Extract Method
系列文
開心撰寫 PHPUnit30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言